package org.jeecg.modules.wlhy.customer.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.modules.paycenter.channel.bankdocking.dto.Acc;
import org.jeecg.modules.paycenter.channel.bankdocking.dto.Cmp;
import org.jeecg.modules.paycenter.channel.bankdocking.dto.RespPacket;
import org.jeecg.modules.paycenter.channel.bankdocking.service.NhBankService;
import org.jeecg.modules.paycenter.channel.bankdocking.utils.BankUtils;
import org.jeecg.modules.paycenter.exception.BankReceiveException;
import org.jeecg.modules.paycenter.exception.BankSendException;
import org.jeecg.modules.wlhy.bill.entity.HyCustomerBill;
import org.jeecg.modules.wlhy.bill.service.IHyCustomerBillService;
import org.jeecg.modules.wlhy.customer.entity.HyCustomer;
import org.jeecg.modules.wlhy.customer.entity.HyCustomerAccountBook;
import org.jeecg.modules.wlhy.customer.mapper.HyCustomerAccountBookMapper;
import org.jeecg.modules.wlhy.customer.service.IHyCustomerAccountBookService;
import org.jeecg.modules.wlhy.hyconfig.entity.HyConfig;
import org.jeecg.modules.wlhy.hycustomerbank.entity.HyCustomerBank;
import org.jeecg.modules.wlhy.shipping.service.IHyShippingNoteService;
import org.jeecg.modules.wlhy.utils.CodeUtil;
import org.jeecg.modules.wlhy.utils.HyConfigUtils;
import org.jeecg.modules.wlhy.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Description: hy_customer_account_book
 * @Author: jeecg-boot
 * @Date:   2021-01-15
 * @Version: V1.0
 */
@Service
@Slf4j
public class HyCustomerAccountBookServiceImpl extends ServiceImpl<HyCustomerAccountBookMapper, HyCustomerAccountBook> implements IHyCustomerAccountBookService {

    @Autowired
    private BankUtils bankUtils;

    @Autowired
    private UserUtil userUtil;

    @Autowired
    private IHyCustomerBillService hyCustomerBillService;

    @Autowired
    private IHyShippingNoteService hyShippingNoteService;

    @Override
    @Transactional
    public void addAccountBook(HyCustomerAccountBook hyCustomerAccountBook) {
        HyCustomer customer = userUtil.getCustomer();
        if(customer==null){
            throw new JeecgBootException("未获取到货主信息");
        }
        //是否开通过
        HyCustomerAccountBook accountBook = this.getOne(
                new QueryWrapper<HyCustomerAccountBook>().eq("customer_id",customer.getId())
        );
        if(accountBook != null){
            throw new JeecgBootException("不能重复开通");
        }
        HyConfig config = HyConfigUtils.getConfig();
        if(!config.getNhbankIzUse()){
            throw new JeecgBootException("未开通服务！");
        }
        String nhbankAccName = config.getNhbankAccName();
        if(StringUtils.isEmpty(nhbankAccName)){
            throw new JeecgBootException("未配置农行账户名称！");
        }

        String logAccNo =  this.createCustomerLogAccNo();
//        String logAccName = customer.getCustomerName();
        String logAccName = nhbankAccName;
        hyCustomerAccountBook.setCustomerId(customer.getId());
        hyCustomerAccountBook.setUserId(customer.getUserId());
        hyCustomerAccountBook.setAccNo(config.getNhbankAccno());
        hyCustomerAccountBook.setProv(config.getNhbankProv());
        hyCustomerAccountBook.setLogAccName(logAccName);
        hyCustomerAccountBook.setLogAccNo(logAccNo);
//        String payPwd = hyCustomerAccountBook.getPayPwd();
//        String encryptPayPwd = PasswordUtil.encrypt(logAccNo, payPwd,  PasswordUtil.BSalt);
//        hyCustomerAccountBook.setPayPwd(encryptPayPwd);
        if( this.save(hyCustomerAccountBook)){
            try {
                RespPacket packet = bankUtils.AddAccountBook(logAccName, logAccNo);
                if(!packet.isSuccess()){
                    throw new JeecgBootException(packet.getRespInfo());
                }
            } catch (Exception e) {
                throw new JeecgBootException(e.getMessage());
            }

        }else {
            throw new JeecgBootException("添加失败");
        }

    }

    @Override
    public Map getAccountBookInfo() throws Exception {
        HyCustomer customer = userUtil.getCustomer();
        if(customer==null){
            throw new JeecgBootException("未获取到货主信息");
        }
        Map<String,Object> data = new HashMap<>();
        data.put("accountPeriod" , null);
        HyCustomerAccountBook hyCustomerAccountBook = this.getAccountBookByCustomerId(customer.getId());
        if(hyCustomerAccountBook != null){
            //更新货主钱包
            Acc customerAcc = this.getCustomerAcc(hyCustomerAccountBook);
            if(customerAcc != null){
                BigDecimal amt = customerAcc.getAvailBal();
                hyCustomerAccountBook.setAmt(amt);
                hyCustomerAccountBook.setAccSts(customerAcc.getAccSts());
                this.updateById(hyCustomerAccountBook);
            }else {
                hyCustomerAccountBook.setAmt(BigDecimal.ZERO);
                hyCustomerAccountBook.setAccSts("-99");
            }
            hyCustomerAccountBook.setPayPwd("");
            hyCustomerAccountBook.setFrzAmt(BigDecimal.ZERO);
            BigDecimal djsAmt = this.getDJSByCustomerId(customer.getId());
            hyCustomerAccountBook.setAvailAmt(djsAmt);//余额替换为 待结算金额

            HyConfig config = HyConfigUtils.getConfig();
            String nhbankBankname="";
            if (config != null) {
                nhbankBankname = config.getNhbankBankname();
            }
            hyCustomerAccountBook.setKhh(nhbankBankname);
            data.put("accountBook" , hyCustomerAccountBook);
        }else {
            data.put("accountBook" , null);
        }
        return data;
    }

    @Override
    public void editPayPwd(String oldPwd, String password) {
        HyCustomer customer = userUtil.getCustomer();
        if(customer==null){
            throw new JeecgBootException("未获取到货主信息");
        }
        HyCustomerAccountBook accountBook = this.getOne(
                new QueryWrapper<HyCustomerAccountBook>().eq("customer_id",customer.getId())
        );
        if(accountBook == null){
            throw new JeecgBootException("未获取到账户信息");
        }
        String encryptPayPwd = PasswordUtil.encrypt(accountBook.getLogAccNo(), oldPwd,  PasswordUtil.BSalt);
        if(!StringUtils.equals(encryptPayPwd,accountBook.getPayPwd())){
            throw new JeecgBootException("原始支付密码错误");
        }
        String newEncryptPayPwd = PasswordUtil.encrypt(accountBook.getLogAccNo(), password,  PasswordUtil.BSalt);
        accountBook.setPayPwd(newEncryptPayPwd);
        if(!this.updateById(accountBook)){
            throw new JeecgBootException("修改失败");
        }
    }

    @Override
    public void ResetPayPwd(String password) {
        HyCustomer customer = userUtil.getCustomer();
        if(customer==null){
            throw new JeecgBootException("未获取到货主信息");
        }
        HyCustomerAccountBook accountBook = this.getOne(
                new QueryWrapper<HyCustomerAccountBook>().eq("customer_id",customer.getId())
        );
        if(accountBook == null){
            throw new JeecgBootException("未获取到账户信息");
        }
        String newEncryptPayPwd = PasswordUtil.encrypt(accountBook.getLogAccNo(), password,  PasswordUtil.BSalt);
        accountBook.setPayPwd(newEncryptPayPwd);
        if(!this.updateById(accountBook)){
            throw new JeecgBootException("修改失败");
        }
    }

    @Override
    public HyCustomerAccountBook getAccountBookByCustomerId(String customerId) {
        HyCustomerAccountBook hyCustomerAccountBook = this.getOne(
                new QueryWrapper<HyCustomerAccountBook>().eq("customer_id",customerId)
        );
        return hyCustomerAccountBook;
    }

    @Override
    public boolean checkPayPwd(String pw, HyCustomerAccountBook accountBook) {
        if(accountBook == null){
            return false;
        }
        if(StringUtils.isEmpty(accountBook.getLogAccNo())){
            return false;
        }
        String encryptPayPwd = PasswordUtil.encrypt(accountBook.getLogAccNo(), pw, PasswordUtil.BSalt);
        if (!StringUtils.equals(encryptPayPwd, accountBook.getPayPwd())) {
            return false;
        }
        return true;
    }

    @Override
    public Acc getCustomerAcc(HyCustomerAccountBook accountBook) {
        try {
            RespPacket packet = bankUtils.getAccountBookBalance(accountBook.getAccNo(), accountBook.getProv(), accountBook.getLogAccNo());
            if(packet.isSuccess()){
                return packet.getAcc();
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("获取货主余额异常: {}, {}",e.getMessage(), JSONUtil.toJsonStr(accountBook));
        }
        return null;
    }

    @Override
    public Map getAcc() {
        HyCustomer customer = userUtil.getCustomer();
        if(customer==null){
            throw new JeecgBootException("未获取到货主信息");
        }
        Map<String,Object> data = new HashMap<>();
        data.put("accountPeriod" , null);
        HyCustomerAccountBook hyCustomerAccountBook = this.getAccountBookByCustomerId(customer.getId());
        if(hyCustomerAccountBook == null){
            data.put("accountBook" , null);
        }else {
            hyCustomerAccountBook.setPayPwd("");
            data.put("accountBook" , hyCustomerAccountBook);
        }
        return data;
    }

    //待结算运费
    @Override
    public BigDecimal getDJSByCustomerId(String customerId) {
//        return baseMapper.getDJSByCustomerId(customerId);
        return hyShippingNoteService.getCustomerDjsFee(customerId);
    }

    @Override
    public Result<?> tx(HyCustomer customer, HyCustomerAccountBook accountBook, HyCustomerBank customerBank, BigDecimal amt) {
        String crAccName = customerBank.getBankName();
        String crAccNo = customerBank.getBankNum();

        RespPacket packet = null;
        String accNo = accountBook.getAccNo();
        String logAccNo = accountBook.getLogAccNo();
        String lsd = CodeUtil.getBillNum();

        HyCustomerBill bill = new HyCustomerBill();
        bill.setBillNum(lsd);
        bill.setBillType("3");//提现
        bill.setCustomerId(customer.getId());
        bill.setDbaccno(accNo);
        bill.setDbaccname(accountBook.getLogAccName());
        bill.setDblogaccno(logAccNo);
        bill.setCraccno(crAccNo);
        bill.setCraccname(crAccName);
        bill.setCrlogaccno("");
        bill.setAmt(amt); //提现金额
        bill.setRespSource("0");
        bill.setRespCode("4");
        bill.setRespInfo("交易成功");
        bill.setPayChannel("1");
        bill.setPayDt(new Date());//支付时间
        bill.setPayChannel(NhBankService.CHANNEL);
        try {
            HyConfig config = HyConfigUtils.getConfig();
            packet = bankUtils.tx(
                    lsd,accountBook.getProv(), "",
                    accNo, logAccNo, config.getNhbankAccName(),
                    crAccNo, crAccName, amt,customerBank.getBankType());
            if(packet.isSuccess()){
                hyCustomerBillService.save(bill);
                return Result.OK("操作成功！");
            }
            bill.setRespSource(packet.getRespSource());
            bill.setRespCode(packet.getRespCode());
            bill.setRespInfo(packet.getRespInfo());
            bill.setRxtInfo(packet.getRxtInfo());
        }  catch (BankSendException e) {
            return Result.error("交易超时,请稍后重试！");
        } catch (BankReceiveException e) {
            //发送成功，但是接收数据后续处理异常
            bill.setRespSource("-1");
            bill.setRespCode("-1");
            bill.setRespInfo("接收交易数据超时,请查询交易状态");
            bill.setRxtInfo("");
        } catch (Exception e) {
            return Result.error("交易失败：" + e.getMessage());
        }
        //查询交易状态
        RespPacket exchangeStatus = getExchangeStatus(lsd);
        String msg = "交易失败";
        if (exchangeStatus != null) {
            if (exchangeStatus.isSuccess()) {
                String transSta = exchangeStatus.getTransSta();
                if ("4".equals(transSta)) {
                    bill.setRespSource("0");
                    bill.setRespCode("4");
                    bill.setRespInfo("交易成功");
                    bill.setRxtInfo("");
                    hyCustomerBillService.save(bill);
                    return Result.OK("操作成功！");
                }else {
                    Cmp cmp = exchangeStatus.getCmp();
                    if(cmp!=null){
                        msg = cmp.getRespPrvData();
                    }
                    bill.setRespSource(transSta);
                    bill.setRespInfo(msg);
                }
            }
        }
        hyCustomerBillService.save(bill);
        return Result.error(msg);
    }

    private RespPacket getExchangeStatus(String billNum) {
        try {
            RespPacket exchangeStatus = bankUtils.getExchangeStatus(billNum);
            return exchangeStatus;
        } catch (Exception e) {
            return null;
        }
    }
    @Override
    public void exchangeStatus(HyCustomerBill customerBill) {
        try {
            RespPacket packet = bankUtils.getExchangeStatus(customerBill.getBillNum());
            if(packet.isSuccess()){
                String transSta = packet.getTransSta();
                if("4".equals(transSta)) {
                    customerBill.setRespSource("0");
                    customerBill.setRespCode("4");
                    customerBill.setRespInfo("交易成功");
                    hyCustomerBillService.updateById(customerBill);
                }else {
                    Cmp cmp = packet.getCmp();
                    String RespInfo = "交易失败";
                    if(cmp!=null){
                        RespInfo = cmp.getRespPrvData();
                    }
                    customerBill.setRespSource(transSta);
                    customerBill.setRespCode("");
                    customerBill.setRespInfo(RespInfo);
                    hyCustomerBillService.updateById(customerBill);
                }
            }
        } catch (Exception ex) {

        }
    }

    @Override
    public String createCustomerLogAccNo() {
        for (int i = 0; i < 10; i++) {
            //todo
            String logAccNo =  "1" + RandomUtil.randomNumbers(9);
            int count = this.count(new QueryWrapper<HyCustomerAccountBook>().eq("log_acc_no",logAccNo));
            if(count == 0) {
                return logAccNo;
            }
        }
        throw new JeecgBootException("生成失败，请重试");
    }

    @Override
    public List<HyCustomerAccountBook> getAccountBookByCustomerIds(Set<String> agentSet) {
        List<HyCustomerAccountBook> accountBooks = this.list(
                new QueryWrapper<HyCustomerAccountBook>().in("customer_id", agentSet)
        );
        return accountBooks;
    }

    @Override
    public HyCustomerAccountBook getWalletInfo(String customerId) {
        HyCustomerAccountBook hyCustomerAccountBook = this.getAccountBookByCustomerId(customerId);
        if(hyCustomerAccountBook == null) {
            return null;
        }

        //更新货主钱包
        Acc customerAcc = this.getCustomerAcc(hyCustomerAccountBook);
        if(customerAcc != null){
            BigDecimal amt = customerAcc.getAvailBal();
            hyCustomerAccountBook.setAmt(amt);
            hyCustomerAccountBook.setAccSts(customerAcc.getAccSts());
        }else {
            hyCustomerAccountBook.setAmt(BigDecimal.ZERO);
            hyCustomerAccountBook.setAccSts("-99");
        }
        hyCustomerAccountBook.setPayPwd("");
        hyCustomerAccountBook.setFrzAmt(BigDecimal.ZERO);
        //待结算金额
        BigDecimal djsAmt = this.getDJSByCustomerId(customerId);
        hyCustomerAccountBook.setAvailAmt(djsAmt);//余额替换为 待结算金额

        HyConfig config = HyConfigUtils.getConfig();
        String nhbankBankname = "";
        if (config != null) {
            nhbankBankname = config.getNhbankBankname();
        }
        hyCustomerAccountBook.setKhh(nhbankBankname);
        return hyCustomerAccountBook;
    }

    @Override
    @Transactional
    public void updateCustomerAccInfo(HyCustomerAccountBook customerAccountBook) throws Exception {
        RespPacket respPacket = bankUtils.editAccountBookName(customerAccountBook.getLogAccNo(), customerAccountBook.getLogAccName());
        if(respPacket.isSuccess()){
            this.updateById(customerAccountBook);
            return;
        }
        throw new Exception(respPacket.getRespInfo());
    }

}
